package com.fanrui.code.util;

import java.lang.reflect.InvocationTargetException;

import org.apache.commons.beanutils.MethodUtils;
import com.google.protobuf.Message.Builder;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import com.google.protobuf.MessageLite;
import com.google.protobuf.util.JsonFormat;
import com.google.protobuf.util.JsonFormat.Printer;
import com.fanrui.proto.cmd.CmdWrapper;
import com.fanrui.proto.cmd.CmdWrapper.CmdType;
import com.fanrui.proto.cmd.CmdWrapper.ResultCode;
import com.fanrui.proto.cmd.ServerCmdWrapper;

public class CommandsUtil {

	/**
	 * 
	 * 直接返回错误码。
	 * 
	 * @param cmd
	 * @return
	 */
	public static CmdWrapper wrapper(int requestNumber, ResultCode errorCode) {
		return CmdWrapper.newBuilder().setCmdNumber(requestNumber).setResultCode(errorCode).build();
	}

	/**
	 * 
	 * 根据 消息类，自动找到对应的 CmdType，设置 CmdWrapper.CmdType字段 （前提是 CmdType中的枚举名 和 消息类 名一一对应）
	 * 
	 * @param cmd
	 * @return
	 */
	public static CmdWrapper wrapper(int requestNumber, MessageLite cmd) {
		// 根据Message的类型找到对应CmdType
		CmdType t = Enum.valueOf(CmdType.class, cmd.getClass().getSimpleName());
		return CmdWrapper.newBuilder().setCmdNumber(requestNumber).setCmdType(t).setT(System.currentTimeMillis())
				.setCmdData(cmd.toByteString()).build();
	}
	
	/**
	 * 
	 * 根据CmdWrapper.CmdType字段，自动找到对应的消息类，解析出CmdData （前提是 CmdType中的枚举名 和
	 * 消息类s名一一对应）
	 * 
	 * @param wrapper
	 * @return
	 */
	public static Message unwrapper(String jsonStr) throws InvalidProtocolBufferException {
		return unwrapper(jsonToCommand(jsonStr));
	}
	public static Message jsonToCommand(String jsonStr,Builder builder) throws InvalidProtocolBufferException{
		JsonFormat.parser().merge(jsonStr, builder);
		return builder.build();
	}
	public static CmdWrapper jsonToCommand(String jsonStr) throws InvalidProtocolBufferException {
		CmdWrapper.Builder builder = CmdWrapper.newBuilder();
		JsonFormat.parser().merge(jsonStr, builder);
		return builder.build();
	}

	/**
	 * 
	 * 根据CmdWrapper.CmdType字段，自动找到对应的消息类，解析出CmdData （前提是 CmdType中的枚举名 和 消息类s名一一对应）
	 * 
	 * @param wrapper
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static Message unwrapper(CmdWrapper wrapper) {
		// 根据CmdType找到Message的类型名
		String className = com.fanrui.proto.cmd.Commands.class.getPackage().getName() + "."
				+ wrapper.getCmdType().name();

		Class<? extends Message> clazz = null;
		try {
			clazz = (Class<? extends Message>) Class.forName(className);
		} catch (ClassNotFoundException e) {
			throw new RuntimeException(e);
		}

		ByteString cmdData = wrapper.getCmdData();

		try {
			return (Message) MethodUtils.invokeStaticMethod(clazz, "parseFrom", cmdData);
		} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
			throw new RuntimeException(e);
		}
	}

	private static Printer jsonFormater = JsonFormat.printer().omittingInsignificantWhitespace();

	/**
	 * 用具体Message的toString替换掉cmd_data。
	 * 
	 * @param wrapper
	 * @return
	 */
	public static String toString(CmdWrapper wrapper) {
		try {
			String wrapperJson = jsonFormater.print(wrapper);
			String cmdJson = jsonFormater.print(unwrapper(wrapper));
			String rtn = wrapperJson.replaceFirst("\"cmdData\":\".*\"", "\"cmdData\":" + cmdJson);
			return rtn;
		} catch (InvalidProtocolBufferException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 用具体Message的toString替换掉cmd_data。
	 * 
	 * @param wrapper
	 * @return
	 */
	public static String toString(Message message) {
		try {
			String cmdJson = jsonFormater.print(message);
			return cmdJson;
		} catch (InvalidProtocolBufferException e) {
			throw new RuntimeException(e);
		}
	}
	/**
	 * 用具体Message的toString替换掉cmd_data。
	 * 
	 * @param wrapper
	 * @return
	 */
	public static String toString(ServerCmdWrapper wrapper) {
		try {
			String wrapperJson = jsonFormater.print(wrapper);
			String cmdJson = jsonFormater.print(unwrapper(wrapper.getCmdWrapper()));
			wrapperJson = wrapperJson.replaceFirst("\"cmdData\":\".*\"", "\"cmdData\":" + cmdJson);
			return wrapperJson;
		} catch (InvalidProtocolBufferException e) {
			throw new RuntimeException(e);
		}
	}
}
